<!DOCTYPE html>
          <head>
        <meta charset="utf-8">
            
            <title>
                「Android」滚轮刻度尺的实现 | ttdevs
            </title>
            <meta content="width=device-width, initial-scale=1" name="viewport">
            <meta name="theme-color" content="#4184f3">
            
            
            <link href="/favicon.ico" rel="icon"/>
            

            <link rel="stylesheet" href="/css/highlight.light.css">
            <link rel="stylesheet" href="/css/prism-customize.css">
            <link rel="stylesheet" href="/css/nav-icon.css">
            <link rel="stylesheet" href="/css/waves.min.css">
            <link rel="stylesheet" href="/css/jquery.tocify.css">
            <link rel="stylesheet" href="/css/main.css">
            <link rel="stylesheet" href="/css/nav-indicator.css">
            
  

  
  <!-- 谷歌统计 -->
  <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-97465173-1', 'auto');
    ga('send', 'pageview');

  </script>
  
            </meta>
        </meta>
    </head>

    <body>
        <header>
            <!-- cover image or sth. -->
        </header>
        <div id="main" class="m-scene">
            
<div class="nav-wrapper">

    <div class="container">
        <nav>
            <div class="logo wave">
                <a href="/" id="logo">
                    ttdevs
                </a>
            </div>
            <div class="nav-toggle-icon" >
                <div class="material-hamburger">
                    <span>
                    </span>
                    <span>
                    </span>
                    <span>
                    </span>
                </div>
            </div>
            <div class="menu-wrapper">
                <div class="nav-indicator">
                </div>
                <ul class="menus">
                    
                     
                        <li>
                            <a class="wave " href="/">
                                首页
                            </a>
                        </li>
                     
                        <li>
                            <a class="wave " href="/archives">
                                归档
                            </a>
                        </li>
                     
                        <li>
                            <a class="wave " href="/about">
                                关于
                            </a>
                        </li>
                     
                    
                   
                </ul>
            </div>
        </nav>
    </div>
</div>
            <div class="container content">
                <div class="scene_element scene_element--fadein">
                    <div class="row">
    <div class="main">
        <article>
          
          <header class="post-header with-cover" style="background-image:url('/1970/01/01/[Android]滚轮刻度尺的实现/cover.jpg')" >
          
          </header>
          <h1 class="post-title">「Android」滚轮刻度尺的实现</h1>

          <section class="post-info">
            <span class="post-date">1970/01/01</span>
            
            <span class="post-category">
                <a class="article-category-link" href="/categories/技术/">技术</a>
            </span>
            
            
            <span class="post-tags">
              <ul class="post-tag-list"><li class="post-tag-list-item"><a class="post-tag-list-link" href="/tags/Android/">Android</a></li></ul>
            </span>
            
          </section>

          <section class="post-content">
            <h2 id="0x00-滚轮刻度尺（卷尺）"><a href="/1970/01/01/[Android]滚轮刻度尺的实现/#0x00-滚轮刻度尺（卷尺）" class="headerlink" title="0x00 滚轮刻度尺（卷尺）"></a>0x00 滚轮刻度尺（卷尺）</h2><p>遇到下面这样一个需求：</p>
<p><img src="http://img.blog.csdn.net/20140831150159887?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdHRkZXZz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="滚轮刻度尺">  </p>
<h2 id="0x01-问题分析"><a href="/1970/01/01/[Android]滚轮刻度尺的实现/#0x01-问题分析" class="headerlink" title="0x01 问题分析"></a>0x01 问题分析</h2><p>卷尺，通过左右滑动来选择不同的刻度值。这方面的东西以前没弄过，以目前你的能力，想了几种思路都死在了半路上。比如上面的刻度线如何弄，滑动的时候又该如何弄；下面的数字又如何弄；看起来像圆圈的效果该如何弄。时间紧迫，就俩晚上的时间。没有好的思路就参考别人的先吧，说来也巧，两天前刚看过一个日期选择控件，还有以前看的一个<a href="http://blog.csdn.net/lilu_leo/article/details/7397697" target="_blank" rel="external">仿iPhone滚动控件</a> ，效果类似：</p>
<p><img src="http://img.blog.csdn.net/20140831151514968?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdHRkZXZz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""> </p>
<p><img src="http://img.blog.csdn.net/20140831151748056?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdHRkZXZz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">  </p>
<p>本想找作者<a href="http://blog.csdn.net/lilu_leo" target="_blank" rel="external">傲慢的上校</a>交流下，但是时间比较紧，源码都给了也不是很好意思。大致的浏览了下，可能涉及下面几个东西：</p>
<ul>
<li>背景：这个用shape实现。之前有研究过，也用过，但是还没实现过要求的效果</li>
<li>刻度和数字：这个就不要乱想了，直接draw。相对来说还是比较简单的，就是画直线和字</li>
<li>滚动：滚动的时候不停的重绘实现一个滚动的效果。弄过，但是不确定实现的是啥样的效果</li>
<li>快速滚动：Scroller和VelocityTracker可能是需要用到的东西。几乎完全没弄过，骚年，学习吧（需求的要求中，这个优先级可以最低）</li>
<li>需求：刻度的单位是可以变的，比如十格一个单位，或者两格一个单位，在或者可以是任意的（这个前期思路没想好，实现起来就困难了，最后只弄了两种）</li>
</ul>
<p>其实，到了这一步基本上就已经可以实现了，看个最终效果先：</p>
<p><img src="http://img.blog.csdn.net/20140831153554458?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdHRkZXZz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">  </p>
<h2 id="0x02-实现"><a href="/1970/01/01/[Android]滚轮刻度尺的实现/#0x02-实现" class="headerlink" title="0x02 实现"></a>0x02 实现</h2><p>下面一步一步来。</p>
<p>在这之前还有个地方要说的，就是控件的接口：对外提供一个方法实现控件初始化和接收控件选择的值：显示的单位，最大值，最小值，当前值，回调接口。有了这些，先从最难的入手。</p>
<ul>
<li>实现刻度和数字，并可以滑动</li>
</ul>
<p>这个地方很关键，每个人有每个人的思路，而且思路的好坏直接影响到后面对不同单位的实现。目前的思路是根据当前显示的数值mValue，从控件中间向两边画刻度线，滑动的时候同时改变显示的值mValue，不足最小刻度的四舍五入：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Override</span></div><div class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDraw</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">   <span class="keyword">super</span>.onDraw(canvas);</div><div class="line"></div><div class="line">   drawScaleLine(canvas);</div><div class="line">   <span class="comment">// drawWheel(canvas);</span></div><div class="line">   drawMiddleLine(canvas);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">drawWheel</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">   Drawable wheel = getResources().getDrawable(R.drawable.bg_wheel);</div><div class="line">   wheel.setBounds(<span class="number">0</span>, <span class="number">0</span>, getWidth(), getHeight());</div><div class="line">   wheel.draw(canvas);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line">* 从中间往两边开始画刻度线</div><div class="line">*</div><div class="line">* <span class="doctag">@param</span> canvas</div><div class="line">*/</div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">drawScaleLine</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">   canvas.save();</div><div class="line"></div><div class="line">   Paint linePaint = <span class="keyword">new</span> Paint();</div><div class="line">   linePaint.setStrokeWidth(<span class="number">2</span>);</div><div class="line">   linePaint.setColor(Color.BLACK);</div><div class="line"></div><div class="line">   TextPaint textPaint = <span class="keyword">new</span> TextPaint(Paint.ANTI_ALIAS_FLAG);</div><div class="line">   textPaint.setTextSize(TEXT_SIZE * mDensity);</div><div class="line"></div><div class="line">   <span class="keyword">int</span> width = mWidth, drawCount = <span class="number">0</span>;</div><div class="line">   <span class="keyword">float</span> xPosition = <span class="number">0</span>, textWidth = Layout.getDesiredWidth(<span class="string">"0"</span>, textPaint);</div><div class="line"></div><div class="line">   <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; drawCount &lt;= <span class="number">4</span> * width; i++) &#123;</div><div class="line">       <span class="keyword">int</span> numSize = String.valueOf(mValue + i).length();</div><div class="line"></div><div class="line">       xPosition = (width / <span class="number">2</span> - mMove) + i * mLineDivider * mDensity;</div><div class="line">       <span class="keyword">if</span> (xPosition + getPaddingRight() &lt; mWidth) &#123;</div><div class="line">           <span class="keyword">if</span> ((mValue + i) % mModType == <span class="number">0</span>) &#123;</div><div class="line">               canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);</div><div class="line"></div><div class="line">               <span class="keyword">if</span> (mValue + i &lt;= mMaxValue) &#123;</div><div class="line">                   <span class="keyword">switch</span> (mModType) &#123;</div><div class="line">                       <span class="keyword">case</span> MOD_TYPE_HALF:</div><div class="line">                           canvas.drawText(String.valueOf((mValue + i) / <span class="number">2</span>), countLeftStart(mValue + i, xPosition, textWidth), getHeight() - textWidth, textPaint);</div><div class="line">                           <span class="keyword">break</span>;</div><div class="line">                       <span class="keyword">case</span> MOD_TYPE_ONE:</div><div class="line">                           canvas.drawText(String.valueOf(mValue + i), xPosition - (textWidth * numSize / <span class="number">2</span>), getHeight() - textWidth, textPaint);</div><div class="line">                           <span class="keyword">break</span>;</div><div class="line"></div><div class="line">                       <span class="keyword">default</span>:</div><div class="line">                           <span class="keyword">break</span>;</div><div class="line">                   &#125;</div><div class="line">               &#125;</div><div class="line">           &#125; <span class="keyword">else</span> &#123;</div><div class="line">               canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);</div><div class="line">           &#125;</div><div class="line">       &#125;</div><div class="line"></div><div class="line">       xPosition = (width / <span class="number">2</span> - mMove) - i * mLineDivider * mDensity;</div><div class="line">       <span class="keyword">if</span> (xPosition &gt; getPaddingLeft()) &#123;</div><div class="line">           <span class="keyword">if</span> ((mValue - i) % mModType == <span class="number">0</span>) &#123;</div><div class="line">               canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);</div><div class="line"></div><div class="line">               <span class="keyword">if</span> (mValue - i &gt;= <span class="number">0</span>) &#123;</div><div class="line">                   <span class="keyword">switch</span> (mModType) &#123;</div><div class="line">                       <span class="keyword">case</span> MOD_TYPE_HALF:</div><div class="line">                           canvas.drawText(String.valueOf((mValue - i) / <span class="number">2</span>), countLeftStart(mValue - i, xPosition, textWidth), getHeight() - textWidth, textPaint);</div><div class="line">                           <span class="keyword">break</span>;</div><div class="line">                       <span class="keyword">case</span> MOD_TYPE_ONE:</div><div class="line">                           canvas.drawText(String.valueOf(mValue - i), xPosition - (textWidth * numSize / <span class="number">2</span>), getHeight() - textWidth, textPaint);</div><div class="line">                           <span class="keyword">break</span>;</div><div class="line"></div><div class="line">                       <span class="keyword">default</span>:</div><div class="line">                           <span class="keyword">break</span>;</div><div class="line">                   &#125;</div><div class="line">               &#125;</div><div class="line">           &#125; <span class="keyword">else</span> &#123;</div><div class="line">               canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);</div><div class="line">           &#125;</div><div class="line">       &#125;</div><div class="line"></div><div class="line">       drawCount += <span class="number">2</span> * mLineDivider * mDensity;</div><div class="line">   &#125;</div><div class="line"></div><div class="line">   canvas.restore();</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ul>
<li>滑动的加速问题</li>
</ul>
<p>这里用到两个类Scroller和VelocityTracker，关于这两个类之后有机会会详细介绍，这里简单提下：VelocityTracker的作用是在用户加速滑动时计算该滑动多远，拿到这个之后通过Scroller来执行滑动过程的计算，最后是真实的“移动”——根据mValue的值进行重绘：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div></pre></td><td class="code"><pre><div class="line"><span class="meta">@Override</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onTouchEvent</span><span class="params">(MotionEvent event)</span> </span>&#123;</div><div class="line">   <span class="keyword">int</span> action = event.getAction();</div><div class="line">   <span class="keyword">int</span> xPosition = (<span class="keyword">int</span>) event.getX();</div><div class="line"></div><div class="line">   <span class="keyword">if</span> (mVelocityTracker == <span class="keyword">null</span>) &#123;</div><div class="line">       mVelocityTracker = VelocityTracker.obtain();</div><div class="line">   &#125;</div><div class="line">   mVelocityTracker.addMovement(event);</div><div class="line"></div><div class="line">   <span class="keyword">switch</span> (action) &#123;</div><div class="line">       <span class="keyword">case</span> MotionEvent.ACTION_DOWN:</div><div class="line"></div><div class="line">           mScroller.forceFinished(<span class="keyword">true</span>);</div><div class="line"></div><div class="line">           mLastX = xPosition;</div><div class="line">           mMove = <span class="number">0</span>;</div><div class="line">           <span class="keyword">break</span>;</div><div class="line">       <span class="keyword">case</span> MotionEvent.ACTION_MOVE:</div><div class="line">           mMove += (mLastX - xPosition);</div><div class="line">           changeMoveAndValue();</div><div class="line">           <span class="keyword">break</span>;</div><div class="line">       <span class="keyword">case</span> MotionEvent.ACTION_UP:</div><div class="line">       <span class="keyword">case</span> MotionEvent.ACTION_CANCEL:</div><div class="line">           countMoveEnd();</div><div class="line">           countVelocityTracker(event);</div><div class="line">           <span class="keyword">return</span> <span class="keyword">false</span>;</div><div class="line">       <span class="comment">// break;</span></div><div class="line">       <span class="keyword">default</span>:</div><div class="line">           <span class="keyword">break</span>;</div><div class="line">   &#125;</div><div class="line"></div><div class="line">   mLastX = xPosition;</div><div class="line">   <span class="keyword">return</span> <span class="keyword">true</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">countVelocityTracker</span><span class="params">(MotionEvent event)</span> </span>&#123;</div><div class="line">   mVelocityTracker.computeCurrentVelocity(<span class="number">1000</span>);</div><div class="line">   <span class="keyword">float</span> xVelocity = mVelocityTracker.getXVelocity();</div><div class="line">   <span class="keyword">if</span> (Math.abs(xVelocity) &gt; mMinVelocity) &#123;</div><div class="line">       mScroller.fling(<span class="number">0</span>, <span class="number">0</span>, (<span class="keyword">int</span>) xVelocity, <span class="number">0</span>, Integer.MIN_VALUE, Integer.MAX_VALUE, <span class="number">0</span>, <span class="number">0</span>);</div><div class="line">   &#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">changeMoveAndValue</span><span class="params">()</span> </span>&#123;</div><div class="line">   <span class="keyword">int</span> tValue = (<span class="keyword">int</span>) (mMove / (mLineDivider * mDensity));</div><div class="line">   <span class="keyword">if</span> (Math.abs(tValue) &gt; <span class="number">0</span>) &#123;</div><div class="line">       mValue += tValue;</div><div class="line">       mMove -= tValue * mLineDivider * mDensity;</div><div class="line">       <span class="keyword">if</span> (mValue &lt;= <span class="number">0</span> || mValue &gt; mMaxValue) &#123;</div><div class="line">           mValue = mValue &lt;= <span class="number">0</span> ? <span class="number">0</span> : mMaxValue;</div><div class="line">           mMove = <span class="number">0</span>;</div><div class="line">           mScroller.forceFinished(<span class="keyword">true</span>);</div><div class="line">       &#125;</div><div class="line">       notifyValueChange();</div><div class="line">   &#125;</div><div class="line">   postInvalidate();</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">countMoveEnd</span><span class="params">()</span> </span>&#123;</div><div class="line">   <span class="keyword">int</span> roundMove = Math.round(mMove / (mLineDivider * mDensity));</div><div class="line">   mValue = mValue + roundMove;</div><div class="line">   mValue = mValue &lt;= <span class="number">0</span> ? <span class="number">0</span> : mValue;</div><div class="line">   mValue = mValue &gt; mMaxValue ? mMaxValue : mValue;</div><div class="line"></div><div class="line">   mLastX = <span class="number">0</span>;</div><div class="line">   mMove = <span class="number">0</span>;</div><div class="line"></div><div class="line">   notifyValueChange();</div><div class="line">   postInvalidate();</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">notifyValueChange</span><span class="params">()</span> </span>&#123;</div><div class="line">   <span class="keyword">if</span> (<span class="keyword">null</span> != mListener) &#123;</div><div class="line">       <span class="keyword">if</span> (mModType == MOD_TYPE_ONE) &#123;</div><div class="line">           mListener.onValueChange(mValue);</div><div class="line">       &#125;</div><div class="line">       <span class="keyword">if</span> (mModType == MOD_TYPE_HALF) &#123;</div><div class="line">           mListener.onValueChange(mValue / <span class="number">2f</span>);</div><div class="line">       &#125;</div><div class="line">   &#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="meta">@Override</span></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">computeScroll</span><span class="params">()</span> </span>&#123;</div><div class="line">   <span class="keyword">super</span>.computeScroll();</div><div class="line">   <span class="keyword">if</span> (mScroller.computeScrollOffset()) &#123;</div><div class="line">       <span class="keyword">if</span> (mScroller.getCurrX() == mScroller.getFinalX()) &#123; <span class="comment">// over</span></div><div class="line">           countMoveEnd();</div><div class="line">       &#125; <span class="keyword">else</span> &#123;</div><div class="line">           <span class="keyword">int</span> xPosition = mScroller.getCurrX();</div><div class="line">           mMove += (mLastX - xPosition);</div><div class="line">           changeMoveAndValue();</div><div class="line">           mLastX = xPosition;</div><div class="line">       &#125;</div><div class="line">   &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ul>
<li>圆圈背景的实现</li>
</ul>
<p>这个用shape来做，可以使用setBackgroundDrawable()来做，也可以在draw中进行直接绘制，效果相同。还有一些细节问题，比如滑动时刻度线超过边界，滑动距离大时候显示不完整等问题，这个只有做了才会发现。下面是shape背景的代码：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">&lt;?xml version="1.0" encoding="utf-8"?&gt;</div><div class="line"><span class="tag">&lt;<span class="name">shape</span> <span class="attr">xmlns:android</span>=<span class="string">"http://schemas.android.com/apk/res/android"</span></span></div><div class="line">   <span class="attr">android:shape</span>=<span class="string">"rectangle"</span> &gt;</div><div class="line">    </div><div class="line">   <span class="comment">&lt;!-- two set color way --&gt;</span></div><div class="line">   <span class="tag">&lt;<span class="name">gradient</span></span></div><div class="line">       <span class="attr">android:angle</span>=<span class="string">"0"</span></div><div class="line">       <span class="attr">android:centerColor</span>=<span class="string">"#66FFFFFF"</span></div><div class="line">       <span class="attr">android:endColor</span>=<span class="string">"#66AAAAAA"</span></div><div class="line">       <span class="attr">android:startColor</span>=<span class="string">"#66AAAAAA"</span> /&gt;</div><div class="line">    </div><div class="line">   <span class="tag">&lt;<span class="name">corners</span> <span class="attr">android:radius</span>=<span class="string">"6dp"</span> /&gt;</span></div><div class="line">    </div><div class="line">   <span class="tag">&lt;<span class="name">stroke</span></span></div><div class="line">       <span class="attr">android:width</span>=<span class="string">"6dp"</span></div><div class="line">       <span class="attr">android:color</span>=<span class="string">"#FF666666"</span> /&gt;</div><div class="line">    </div><div class="line"><span class="tag">&lt;/<span class="name">shape</span>&gt;</span></div></pre></td></tr></table></figure>
<p>用代码可以这样写：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">private</span> GradientDrawable <span class="title">createBackground</span><span class="params">()</span> </span>&#123;</div><div class="line">   <span class="keyword">float</span> strokeWidth = <span class="number">4</span> * mDensity; <span class="comment">// 边框宽度</span></div><div class="line">   <span class="keyword">float</span> roundRadius = <span class="number">6</span> * mDensity; <span class="comment">// 圆角半径</span></div><div class="line">   <span class="keyword">int</span> strokeColor = Color.parseColor(<span class="string">"#FF666666"</span>);<span class="comment">// 边框颜色</span></div><div class="line">   <span class="comment">// int fillColor = Color.parseColor("#DFDFE0");// 内部填充颜色</span></div><div class="line"></div><div class="line">   setPadding((<span class="keyword">int</span>) strokeWidth, (<span class="keyword">int</span>) strokeWidth, (<span class="keyword">int</span>) strokeWidth, <span class="number">0</span>);</div><div class="line"></div><div class="line">   <span class="keyword">int</span> colors[] = &#123;<span class="number">0xFF999999</span>, <span class="number">0xFFFFFFFF</span>, <span class="number">0xFF999999</span>&#125;;<span class="comment">// 分别为开始颜色，中间夜色，结束颜色</span></div><div class="line">   GradientDrawable bgDrawable = <span class="keyword">new</span> GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);<span class="comment">// 创建drawable</span></div><div class="line">   <span class="comment">// bgDrawable.setColor(fillColor);</span></div><div class="line">   bgDrawable.setCornerRadius(roundRadius);</div><div class="line">   bgDrawable.setStroke((<span class="keyword">int</span>) strokeWidth, strokeColor);</div><div class="line">   <span class="comment">// setBackgroundDrawable(gd);</span></div><div class="line">   <span class="keyword">return</span> bgDrawable;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h2 id="0x03-完整的代码"><a href="/1970/01/01/[Android]滚轮刻度尺的实现/#0x03-完整的代码" class="headerlink" title="0x03 完整的代码"></a>0x03 完整的代码</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div><div class="line">168</div><div class="line">169</div><div class="line">170</div><div class="line">171</div><div class="line">172</div><div class="line">173</div><div class="line">174</div><div class="line">175</div><div class="line">176</div><div class="line">177</div><div class="line">178</div><div class="line">179</div><div class="line">180</div><div class="line">181</div><div class="line">182</div><div class="line">183</div><div class="line">184</div><div class="line">185</div><div class="line">186</div><div class="line">187</div><div class="line">188</div><div class="line">189</div><div class="line">190</div><div class="line">191</div><div class="line">192</div><div class="line">193</div><div class="line">194</div><div class="line">195</div><div class="line">196</div><div class="line">197</div><div class="line">198</div><div class="line">199</div><div class="line">200</div><div class="line">201</div><div class="line">202</div><div class="line">203</div><div class="line">204</div><div class="line">205</div><div class="line">206</div><div class="line">207</div><div class="line">208</div><div class="line">209</div><div class="line">210</div><div class="line">211</div><div class="line">212</div><div class="line">213</div><div class="line">214</div><div class="line">215</div><div class="line">216</div><div class="line">217</div><div class="line">218</div><div class="line">219</div><div class="line">220</div><div class="line">221</div><div class="line">222</div><div class="line">223</div><div class="line">224</div><div class="line">225</div><div class="line">226</div><div class="line">227</div><div class="line">228</div><div class="line">229</div><div class="line">230</div><div class="line">231</div><div class="line">232</div><div class="line">233</div><div class="line">234</div><div class="line">235</div><div class="line">236</div><div class="line">237</div><div class="line">238</div><div class="line">239</div><div class="line">240</div><div class="line">241</div><div class="line">242</div><div class="line">243</div><div class="line">244</div><div class="line">245</div><div class="line">246</div><div class="line">247</div><div class="line">248</div><div class="line">249</div><div class="line">250</div><div class="line">251</div><div class="line">252</div><div class="line">253</div><div class="line">254</div><div class="line">255</div><div class="line">256</div><div class="line">257</div><div class="line">258</div><div class="line">259</div><div class="line">260</div><div class="line">261</div><div class="line">262</div><div class="line">263</div><div class="line">264</div><div class="line">265</div><div class="line">266</div><div class="line">267</div><div class="line">268</div><div class="line">269</div><div class="line">270</div><div class="line">271</div><div class="line">272</div><div class="line">273</div><div class="line">274</div><div class="line">275</div><div class="line">276</div><div class="line">277</div><div class="line">278</div><div class="line">279</div><div class="line">280</div><div class="line">281</div><div class="line">282</div><div class="line">283</div><div class="line">284</div><div class="line">285</div><div class="line">286</div><div class="line">287</div><div class="line">288</div><div class="line">289</div><div class="line">290</div><div class="line">291</div><div class="line">292</div><div class="line">293</div><div class="line">294</div><div class="line">295</div><div class="line">296</div><div class="line">297</div><div class="line">298</div><div class="line">299</div><div class="line">300</div><div class="line">301</div><div class="line">302</div><div class="line">303</div><div class="line">304</div><div class="line">305</div><div class="line">306</div><div class="line">307</div><div class="line">308</div><div class="line">309</div><div class="line">310</div><div class="line">311</div><div class="line">312</div><div class="line">313</div><div class="line">314</div><div class="line">315</div><div class="line">316</div><div class="line">317</div><div class="line">318</div><div class="line">319</div><div class="line">320</div><div class="line">321</div><div class="line">322</div><div class="line">323</div><div class="line">324</div><div class="line">325</div><div class="line">326</div><div class="line">327</div><div class="line">328</div><div class="line">329</div><div class="line">330</div><div class="line">331</div><div class="line">332</div><div class="line">333</div><div class="line">334</div><div class="line">335</div><div class="line">336</div><div class="line">337</div><div class="line">338</div><div class="line">339</div><div class="line">340</div><div class="line">341</div><div class="line">342</div><div class="line">343</div><div class="line">344</div><div class="line">345</div><div class="line">346</div><div class="line">347</div><div class="line">348</div><div class="line">349</div><div class="line">350</div><div class="line">351</div><div class="line">352</div><div class="line">353</div><div class="line">354</div><div class="line">355</div><div class="line">356</div><div class="line">357</div><div class="line">358</div><div class="line">359</div><div class="line">360</div><div class="line">361</div><div class="line">362</div><div class="line">363</div><div class="line">364</div><div class="line">365</div><div class="line">366</div><div class="line">367</div><div class="line">368</div><div class="line">369</div><div class="line">370</div><div class="line">371</div><div class="line">372</div><div class="line">373</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> com.ttdevs.wheel.widget;</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * 卷尺控件类。由于时间比较紧，只有下班后有时间，因此只实现了基本功能。&lt;br&gt;</div><div class="line"> * 细节问题包括滑动过程中widget边缘的刻度显示问题等&lt;br&gt;</div><div class="line"> * &lt;p&gt;</div><div class="line"> * 周末有时间会继续更新&lt;br&gt;</div><div class="line"> *</div><div class="line"> * <span class="doctag">@author</span> ttdevs</div><div class="line"> * <span class="doctag">@version</span> create：2014年8月26日</div><div class="line"> */</div><div class="line"><span class="meta">@SuppressLint</span>(<span class="string">"ClickableViewAccessibility"</span>)</div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TuneWheel</span> <span class="keyword">extends</span> <span class="title">View</span> </span>&#123;</div><div class="line"></div><div class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">OnValueChangeListener</span> </span>&#123;</div><div class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onValueChange</span><span class="params">(<span class="keyword">float</span> value)</span></span>;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> MOD_TYPE_HALF = <span class="number">2</span>;</div><div class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> MOD_TYPE_ONE = <span class="number">10</span>;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ITEM_HALF_DIVIDER = <span class="number">40</span>;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ITEM_ONE_DIVIDER = <span class="number">10</span>;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ITEM_MAX_HEIGHT = <span class="number">50</span>;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ITEM_MIN_HEIGHT = <span class="number">20</span>;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TEXT_SIZE = <span class="number">18</span>;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">float</span> mDensity;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">int</span> mValue = <span class="number">50</span>, mMaxValue = <span class="number">100</span>, mModType = MOD_TYPE_HALF, mLineDivider = ITEM_HALF_DIVIDER;</div><div class="line">    <span class="comment">// private int mValue = 50, mMaxValue = 500, mModType = MOD_TYPE_ONE,</span></div><div class="line">    <span class="comment">// mLineDivider = ITEM_ONE_DIVIDER;</span></div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">int</span> mLastX, mMove;</div><div class="line">    <span class="keyword">private</span> <span class="keyword">int</span> mWidth, mHeight;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keyword">int</span> mMinVelocity;</div><div class="line">    <span class="keyword">private</span> Scroller mScroller;</div><div class="line">    <span class="keyword">private</span> VelocityTracker mVelocityTracker;</div><div class="line"></div><div class="line">    <span class="keyword">private</span> OnValueChangeListener mListener;</div><div class="line"></div><div class="line">    <span class="meta">@SuppressWarnings</span>(<span class="string">"deprecation"</span>)</div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="title">TuneWheel</span><span class="params">(Context context, AttributeSet attrs)</span> </span>&#123;</div><div class="line">        <span class="keyword">super</span>(context, attrs);</div><div class="line"></div><div class="line">        mScroller = <span class="keyword">new</span> Scroller(getContext());</div><div class="line">        mDensity = getContext().getResources().getDisplayMetrics().density;</div><div class="line"></div><div class="line">        mMinVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();</div><div class="line"></div><div class="line">        <span class="comment">// setBackgroundResource(R.drawable.bg_wheel);</span></div><div class="line">        setBackgroundDrawable(createBackground());</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">private</span> GradientDrawable <span class="title">createBackground</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">float</span> strokeWidth = <span class="number">4</span> * mDensity; <span class="comment">// 边框宽度</span></div><div class="line">        <span class="keyword">float</span> roundRadius = <span class="number">6</span> * mDensity; <span class="comment">// 圆角半径</span></div><div class="line">        <span class="keyword">int</span> strokeColor = Color.parseColor(<span class="string">"#FF666666"</span>);<span class="comment">// 边框颜色</span></div><div class="line">        <span class="comment">// int fillColor = Color.parseColor("#DFDFE0");// 内部填充颜色</span></div><div class="line"></div><div class="line">        setPadding((<span class="keyword">int</span>) strokeWidth, (<span class="keyword">int</span>) strokeWidth, (<span class="keyword">int</span>) strokeWidth, <span class="number">0</span>);</div><div class="line"></div><div class="line">        <span class="keyword">int</span> colors[] = &#123;<span class="number">0xFF999999</span>, <span class="number">0xFFFFFFFF</span>, <span class="number">0xFF999999</span>&#125;;<span class="comment">// 分别为开始颜色，中间夜色，结束颜色</span></div><div class="line">        GradientDrawable bgDrawable = <span class="keyword">new</span> GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);<span class="comment">// 创建drawable</span></div><div class="line">        <span class="comment">// bgDrawable.setColor(fillColor);</span></div><div class="line">        bgDrawable.setCornerRadius(roundRadius);</div><div class="line">        bgDrawable.setStroke((<span class="keyword">int</span>) strokeWidth, strokeColor);</div><div class="line">        <span class="comment">// setBackgroundDrawable(gd);</span></div><div class="line">        <span class="keyword">return</span> bgDrawable;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">/**</span></div><div class="line">     * 考虑可扩展，但是时间紧迫，只可以支持两种类型效果图中两种类型</div><div class="line">     *</div><div class="line">     * <span class="doctag">@param</span> value    初始值</div><div class="line">     * <span class="doctag">@param</span> maxValue 最大值</div><div class="line">     * <span class="doctag">@param</span> model    刻度盘精度：&lt;br&gt;</div><div class="line">     *                 &#123;<span class="doctag">@link</span> MOD_TYPE_HALF&#125;&lt;br&gt;</div><div class="line">     *                 &#123;<span class="doctag">@link</span> MOD_TYPE_ONE&#125;&lt;br&gt;</div><div class="line">     */</div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">initViewParam</span><span class="params">(<span class="keyword">int</span> defaultValue, <span class="keyword">int</span> maxValue, <span class="keyword">int</span> model)</span> </span>&#123;</div><div class="line">        <span class="keyword">switch</span> (model) &#123;</div><div class="line">            <span class="keyword">case</span> MOD_TYPE_HALF:</div><div class="line">                mModType = MOD_TYPE_HALF;</div><div class="line">                mLineDivider = ITEM_HALF_DIVIDER;</div><div class="line">                mValue = defaultValue * <span class="number">2</span>;</div><div class="line">                mMaxValue = maxValue * <span class="number">2</span>;</div><div class="line">                <span class="keyword">break</span>;</div><div class="line">            <span class="keyword">case</span> MOD_TYPE_ONE:</div><div class="line">                mModType = MOD_TYPE_ONE;</div><div class="line">                mLineDivider = ITEM_ONE_DIVIDER;</div><div class="line">                mValue = defaultValue;</div><div class="line">                mMaxValue = maxValue;</div><div class="line">                <span class="keyword">break</span>;</div><div class="line"></div><div class="line">            <span class="keyword">default</span>:</div><div class="line">                <span class="keyword">break</span>;</div><div class="line">        &#125;</div><div class="line">        invalidate();</div><div class="line"></div><div class="line">        mLastX = <span class="number">0</span>;</div><div class="line">        mMove = <span class="number">0</span>;</div><div class="line">        notifyValueChange();</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">/**</span></div><div class="line">     * 设置用于接收结果的监听器</div><div class="line">     *</div><div class="line">     * <span class="doctag">@param</span> listener</div><div class="line">     */</div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setValueChangeListener</span><span class="params">(OnValueChangeListener listener)</span> </span>&#123;</div><div class="line">        mListener = listener;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">/**</span></div><div class="line">     * 获取当前刻度值</div><div class="line">     *</div><div class="line">     * <span class="doctag">@return</span></div><div class="line">     */</div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">float</span> <span class="title">getValue</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">return</span> mValue;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onLayout</span><span class="params">(<span class="keyword">boolean</span> changed, <span class="keyword">int</span> left, <span class="keyword">int</span> top, <span class="keyword">int</span> right, <span class="keyword">int</span> bottom)</span> </span>&#123;</div><div class="line">        mWidth = getWidth();</div><div class="line">        mHeight = getHeight();</div><div class="line">        <span class="keyword">super</span>.onLayout(changed, left, top, right, bottom);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDraw</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">        <span class="keyword">super</span>.onDraw(canvas);</div><div class="line"></div><div class="line">        drawScaleLine(canvas);</div><div class="line">        <span class="comment">// drawWheel(canvas);</span></div><div class="line">        drawMiddleLine(canvas);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">drawWheel</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">        Drawable wheel = getResources().getDrawable(R.drawable.bg_wheel);</div><div class="line">        wheel.setBounds(<span class="number">0</span>, <span class="number">0</span>, getWidth(), getHeight());</div><div class="line">        wheel.draw(canvas);</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">/**</span></div><div class="line">     * 从中间往两边开始画刻度线</div><div class="line">     *</div><div class="line">     * <span class="doctag">@param</span> canvas</div><div class="line">     */</div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">drawScaleLine</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">        canvas.save();</div><div class="line"></div><div class="line">        Paint linePaint = <span class="keyword">new</span> Paint();</div><div class="line">        linePaint.setStrokeWidth(<span class="number">2</span>);</div><div class="line">        linePaint.setColor(Color.BLACK);</div><div class="line"></div><div class="line">        TextPaint textPaint = <span class="keyword">new</span> TextPaint(Paint.ANTI_ALIAS_FLAG);</div><div class="line">        textPaint.setTextSize(TEXT_SIZE * mDensity);</div><div class="line"></div><div class="line">        <span class="keyword">int</span> width = mWidth, drawCount = <span class="number">0</span>;</div><div class="line">        <span class="keyword">float</span> xPosition = <span class="number">0</span>, textWidth = Layout.getDesiredWidth(<span class="string">"0"</span>, textPaint);</div><div class="line"></div><div class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; drawCount &lt;= <span class="number">4</span> * width; i++) &#123;</div><div class="line">            <span class="keyword">int</span> numSize = String.valueOf(mValue + i).length();</div><div class="line"></div><div class="line">            xPosition = (width / <span class="number">2</span> - mMove) + i * mLineDivider * mDensity;</div><div class="line">            <span class="keyword">if</span> (xPosition + getPaddingRight() &lt; mWidth) &#123;</div><div class="line">                <span class="keyword">if</span> ((mValue + i) % mModType == <span class="number">0</span>) &#123;</div><div class="line">                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);</div><div class="line"></div><div class="line">                    <span class="keyword">if</span> (mValue + i &lt;= mMaxValue) &#123;</div><div class="line">                        <span class="keyword">switch</span> (mModType) &#123;</div><div class="line">                            <span class="keyword">case</span> MOD_TYPE_HALF:</div><div class="line">                                canvas.drawText(String.valueOf((mValue + i) / <span class="number">2</span>), countLeftStart(mValue + i, xPosition, textWidth), getHeight() - textWidth, textPaint);</div><div class="line">                                <span class="keyword">break</span>;</div><div class="line">                            <span class="keyword">case</span> MOD_TYPE_ONE:</div><div class="line">                                canvas.drawText(String.valueOf(mValue + i), xPosition - (textWidth * numSize / <span class="number">2</span>), getHeight() - textWidth, textPaint);</div><div class="line">                                <span class="keyword">break</span>;</div><div class="line"></div><div class="line">                            <span class="keyword">default</span>:</div><div class="line">                                <span class="keyword">break</span>;</div><div class="line">                        &#125;</div><div class="line">                    &#125;</div><div class="line">                &#125; <span class="keyword">else</span> &#123;</div><div class="line">                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);</div><div class="line">                &#125;</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            xPosition = (width / <span class="number">2</span> - mMove) - i * mLineDivider * mDensity;</div><div class="line">            <span class="keyword">if</span> (xPosition &gt; getPaddingLeft()) &#123;</div><div class="line">                <span class="keyword">if</span> ((mValue - i) % mModType == <span class="number">0</span>) &#123;</div><div class="line">                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);</div><div class="line"></div><div class="line">                    <span class="keyword">if</span> (mValue - i &gt;= <span class="number">0</span>) &#123;</div><div class="line">                        <span class="keyword">switch</span> (mModType) &#123;</div><div class="line">                            <span class="keyword">case</span> MOD_TYPE_HALF:</div><div class="line">                                canvas.drawText(String.valueOf((mValue - i) / <span class="number">2</span>), countLeftStart(mValue - i, xPosition, textWidth), getHeight() - textWidth, textPaint);</div><div class="line">                                <span class="keyword">break</span>;</div><div class="line">                            <span class="keyword">case</span> MOD_TYPE_ONE:</div><div class="line">                                canvas.drawText(String.valueOf(mValue - i), xPosition - (textWidth * numSize / <span class="number">2</span>), getHeight() - textWidth, textPaint);</div><div class="line">                                <span class="keyword">break</span>;</div><div class="line"></div><div class="line">                            <span class="keyword">default</span>:</div><div class="line">                                <span class="keyword">break</span>;</div><div class="line">                        &#125;</div><div class="line">                    &#125;</div><div class="line">                &#125; <span class="keyword">else</span> &#123;</div><div class="line">                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);</div><div class="line">                &#125;</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            drawCount += <span class="number">2</span> * mLineDivider * mDensity;</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        canvas.restore();</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">/**</span></div><div class="line">     * 计算没有数字显示位置的辅助方法</div><div class="line">     *</div><div class="line">     * <span class="doctag">@param</span> value</div><div class="line">     * <span class="doctag">@param</span> xPosition</div><div class="line">     * <span class="doctag">@param</span> textWidth</div><div class="line">     * <span class="doctag">@return</span></div><div class="line">     */</div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">float</span> <span class="title">countLeftStart</span><span class="params">(<span class="keyword">int</span> value, <span class="keyword">float</span> xPosition, <span class="keyword">float</span> textWidth)</span> </span>&#123;</div><div class="line">        <span class="keyword">float</span> xp = <span class="number">0f</span>;</div><div class="line">        <span class="keyword">if</span> (value &lt; <span class="number">20</span>) &#123;</div><div class="line">            xp = xPosition - (textWidth * <span class="number">1</span> / <span class="number">2</span>);</div><div class="line">        &#125; <span class="keyword">else</span> &#123;</div><div class="line">            xp = xPosition - (textWidth * <span class="number">2</span> / <span class="number">2</span>);</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">return</span> xp;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">/**</span></div><div class="line">     * 画中间的红色指示线、阴影等。指示线两端简单的用了两个矩形代替</div><div class="line">     *</div><div class="line">     * <span class="doctag">@param</span> canvas</div><div class="line">     */</div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">drawMiddleLine</span><span class="params">(Canvas canvas)</span> </span>&#123;</div><div class="line">        <span class="comment">// TOOD 常量太多，暂时放这，最终会放在类的开始，放远了怕很快忘记</span></div><div class="line">        <span class="keyword">int</span> gap = <span class="number">12</span>, indexWidth = <span class="number">8</span>, indexTitleWidth = <span class="number">24</span>, indexTitleHight = <span class="number">10</span>, shadow = <span class="number">6</span>;</div><div class="line">        String color = <span class="string">"#66999999"</span>;</div><div class="line"></div><div class="line">        canvas.save();</div><div class="line"></div><div class="line">        Paint redPaint = <span class="keyword">new</span> Paint();</div><div class="line">        redPaint.setStrokeWidth(indexWidth);</div><div class="line">        redPaint.setColor(Color.RED);</div><div class="line">        canvas.drawLine(mWidth / <span class="number">2</span>, <span class="number">0</span>, mWidth / <span class="number">2</span>, mHeight, redPaint);</div><div class="line"></div><div class="line">        Paint ovalPaint = <span class="keyword">new</span> Paint();</div><div class="line">        ovalPaint.setColor(Color.RED);</div><div class="line">        ovalPaint.setStrokeWidth(indexTitleWidth);</div><div class="line">        canvas.drawLine(mWidth / <span class="number">2</span>, <span class="number">0</span>, mWidth / <span class="number">2</span>, indexTitleHight, ovalPaint);</div><div class="line">        canvas.drawLine(mWidth / <span class="number">2</span>, mHeight - indexTitleHight, mWidth / <span class="number">2</span>, mHeight, ovalPaint);</div><div class="line"></div><div class="line">        <span class="comment">// RectF ovalRectF = new RectF(mWidth / 2 - 10, 0, mWidth / 2 + 10, 4 *</span></div><div class="line">        <span class="comment">// mDensity); //TODO 椭圆</span></div><div class="line">        <span class="comment">// canvas.drawOval(ovalRectF, ovalPaint);</span></div><div class="line">        <span class="comment">// ovalRectF.set(mWidth / 2 - 10, mHeight - 8 * mDensity, mWidth / 2 +</span></div><div class="line">        <span class="comment">// 10, mHeight); //TODO</span></div><div class="line"></div><div class="line">        Paint shadowPaint = <span class="keyword">new</span> Paint();</div><div class="line">        shadowPaint.setStrokeWidth(shadow);</div><div class="line">        shadowPaint.setColor(Color.parseColor(color));</div><div class="line">        canvas.drawLine(mWidth / <span class="number">2</span> + gap, <span class="number">0</span>, mWidth / <span class="number">2</span> + gap, mHeight, shadowPaint);</div><div class="line"></div><div class="line">        canvas.restore();</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onTouchEvent</span><span class="params">(MotionEvent event)</span> </span>&#123;</div><div class="line">        <span class="keyword">int</span> action = event.getAction();</div><div class="line">        <span class="keyword">int</span> xPosition = (<span class="keyword">int</span>) event.getX();</div><div class="line"></div><div class="line">        <span class="keyword">if</span> (mVelocityTracker == <span class="keyword">null</span>) &#123;</div><div class="line">            mVelocityTracker = VelocityTracker.obtain();</div><div class="line">        &#125;</div><div class="line">        mVelocityTracker.addMovement(event);</div><div class="line"></div><div class="line">        <span class="keyword">switch</span> (action) &#123;</div><div class="line">            <span class="keyword">case</span> MotionEvent.ACTION_DOWN:</div><div class="line"></div><div class="line">                mScroller.forceFinished(<span class="keyword">true</span>);</div><div class="line"></div><div class="line">                mLastX = xPosition;</div><div class="line">                mMove = <span class="number">0</span>;</div><div class="line">                <span class="keyword">break</span>;</div><div class="line">            <span class="keyword">case</span> MotionEvent.ACTION_MOVE:</div><div class="line">                mMove += (mLastX - xPosition);</div><div class="line">                changeMoveAndValue();</div><div class="line">                <span class="keyword">break</span>;</div><div class="line">            <span class="keyword">case</span> MotionEvent.ACTION_UP:</div><div class="line">            <span class="keyword">case</span> MotionEvent.ACTION_CANCEL:</div><div class="line">                countMoveEnd();</div><div class="line">                countVelocityTracker(event);</div><div class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</div><div class="line">            <span class="comment">// break;</span></div><div class="line">            <span class="keyword">default</span>:</div><div class="line">                <span class="keyword">break</span>;</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        mLastX = xPosition;</div><div class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">countVelocityTracker</span><span class="params">(MotionEvent event)</span> </span>&#123;</div><div class="line">        mVelocityTracker.computeCurrentVelocity(<span class="number">1000</span>);</div><div class="line">        <span class="keyword">float</span> xVelocity = mVelocityTracker.getXVelocity();</div><div class="line">        <span class="keyword">if</span> (Math.abs(xVelocity) &gt; mMinVelocity) &#123;</div><div class="line">            mScroller.fling(<span class="number">0</span>, <span class="number">0</span>, (<span class="keyword">int</span>) xVelocity, <span class="number">0</span>, Integer.MIN_VALUE, Integer.MAX_VALUE, <span class="number">0</span>, <span class="number">0</span>);</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">changeMoveAndValue</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">int</span> tValue = (<span class="keyword">int</span>) (mMove / (mLineDivider * mDensity));</div><div class="line">        <span class="keyword">if</span> (Math.abs(tValue) &gt; <span class="number">0</span>) &#123;</div><div class="line">            mValue += tValue;</div><div class="line">            mMove -= tValue * mLineDivider * mDensity;</div><div class="line">            <span class="keyword">if</span> (mValue &lt;= <span class="number">0</span> || mValue &gt; mMaxValue) &#123;</div><div class="line">                mValue = mValue &lt;= <span class="number">0</span> ? <span class="number">0</span> : mMaxValue;</div><div class="line">                mMove = <span class="number">0</span>;</div><div class="line">                mScroller.forceFinished(<span class="keyword">true</span>);</div><div class="line">            &#125;</div><div class="line">            notifyValueChange();</div><div class="line">        &#125;</div><div class="line">        postInvalidate();</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">countMoveEnd</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">int</span> roundMove = Math.round(mMove / (mLineDivider * mDensity));</div><div class="line">        mValue = mValue + roundMove;</div><div class="line">        mValue = mValue &lt;= <span class="number">0</span> ? <span class="number">0</span> : mValue;</div><div class="line">        mValue = mValue &gt; mMaxValue ? mMaxValue : mValue;</div><div class="line"></div><div class="line">        mLastX = <span class="number">0</span>;</div><div class="line">        mMove = <span class="number">0</span>;</div><div class="line"></div><div class="line">        notifyValueChange();</div><div class="line">        postInvalidate();</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">notifyValueChange</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">if</span> (<span class="keyword">null</span> != mListener) &#123;</div><div class="line">            <span class="keyword">if</span> (mModType == MOD_TYPE_ONE) &#123;</div><div class="line">                mListener.onValueChange(mValue);</div><div class="line">            &#125;</div><div class="line">            <span class="keyword">if</span> (mModType == MOD_TYPE_HALF) &#123;</div><div class="line">                mListener.onValueChange(mValue / <span class="number">2f</span>);</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="meta">@Override</span></div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">computeScroll</span><span class="params">()</span> </span>&#123;</div><div class="line">        <span class="keyword">super</span>.computeScroll();</div><div class="line">        <span class="keyword">if</span> (mScroller.computeScrollOffset()) &#123;</div><div class="line">            <span class="keyword">if</span> (mScroller.getCurrX() == mScroller.getFinalX()) &#123; <span class="comment">// over</span></div><div class="line">                countMoveEnd();</div><div class="line">            &#125; <span class="keyword">else</span> &#123;</div><div class="line">                <span class="keyword">int</span> xPosition = mScroller.getCurrX();</div><div class="line">                mMove += (mLastX - xPosition);</div><div class="line">                changeMoveAndValue();</div><div class="line">                mLastX = xPosition;</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>

          </section>
        </article>
        

       
        <div class="pager">
          
            <a class="post-prev pager-item" href="/1970/01/01/[Android]通过Intent传递数据/" >
              <strong class="article-nav-caption">上一篇</strong>
              <p class="post-nav-title">「Android」通过Intent传递数据</p>
            </a>
          
          
            <a class="post-next pager-item" href="/1970/01/01/[Android]对App进行代码混淆/">
              <strong class="article-nav-caption">下一篇</strong>
              <p class="post-nav-title">「Android」对App进行代码混淆</p>
            </a>
          
        </div>
        

         <!-- comments -->
        <div class="comment-section">
  
    


</div>

    </div>
    
    <aside>
        <div id="toc">
        </div>
    </aside>
    
</div>

                </div>
            </div>
        </div>
        <footer class="footer">
    <p>由<a href="http://hexo.io/" target="_blank">Hexo</a>强力驱动，搭载<a href="https://github.com/wayou/hexo-theme-gstyle">gstyle</a>主题</p>
    <p>
        &copy; 2017 ttdevs
    </p>
</footer>
<script src="/lib/jquery.js"></script>
<script src="/lib/waves.js"></script>
<script src="/lib/jquery-ui.js"></script>
<script src="/lib/jquery.tocify.js"></script>
<script src="/js/main.js"></script>

    </body>
</html>
